<?php
/**
 * 公共函数库
 */
/**
 * 获取或者设置、销毁$_SESSION
 * @param  string  $key   键
 * @param  string  $value 值
 * @return string         设置、获取、销毁是返回的结果
 */
function session($key=0,$value='null')
{
    if(!is_string($key)){
        return false;
    }elseif($key===null){
        unset($_SESSION);
        return 'All session was unset !';
    }

    if($value===null){
        unset($_SESSION[$key]);
        return "The session.{$key} was unset !";
    }elseif($value!=='null'){
        $_SESSION[$key]=$value;
        return $value;
    }else{
        $result=$_SESSION[$key]?:false;
    }
    
    return $result;
}
/**
 * 友好显示变量
 * @param  mixed $var 待输出的变量
 * @return mixed      浏览器中输出，友好显示
 */
function dump($var)
{
    if(is_bool($var)){
        var_dump($var);
    }else if(is_null($var)){
        var_dump(NULL);
    }else{
        header("Content-type:text/html;charset=utf-8");
        echo "<pre>";
        var_dump($var);
        echo "</pre>";
    }
}

/**
 * 友好显示变量
 * 调用dump()函数
 * @param  mixed $var 待输出的变量
 * @return mixed      浏览器中输出，友好显示
 */
function dd($var='调试中...')
{
    dump($var);
    exit();
}

/**
 * 友好显示变量
 * @param  mixed $var 待输出的变量
 * @return mixed      浏览器中输出，友好显示
 */
function export($var)
{
    header("Content-type:text/html;charset=utf-8");
    echo '<pre>';
    var_export($var);
    echo '</pre>';
}

/**
 * 友好显示变量
 * 调用dump()函数
 * @param  mixed $var 待输出的变量
 * @return mixed      浏览器中输出，友好显示
 */
function vee($var='调试中...')
{
    export($var);
    exit();
}

/**
 * 实例化模型类，用于数据库操作
 * @param string $table 模型层数据表操作类，与数据表同名（驼峰与下划线对应）
 * @return  mixed 是一个通过单例、工厂产生的对象
 */
function M($table)
{
    static $pdo=null;
    // 获取数据库配置
    $db_user=config('DB_USER');
    $db_passwd=config('DB_PASSWORD');
    $db_prefix=config('DB_PREFIX');
    // 获取 DSN 存在则直接使用 DSN、不存在则使用数据库配置组合 DSN
    $dsn = config('DB_DSN');
    if(empty($dsn)){
        $db_type=config('DB_TYPE');
        $db_host=config('DB_HOST');
        $db_name=config('DB_NAME');
        $db_charset=config('DB_CHARSET');
        $dsn = "{$db_type}:host={$db_host};dbname={$db_name};charset={$db_charset}";
    }
    try{
        // 1、2、3、连接数据库
        if(empty($pdo)){
            $pdo = new \PDO($dsn,$db_user,$db_passwd);
        }
    }catch(\PDOException $e){
        exit($e->getMessage());
    }
    $app=basename(APP_PATH);
    $model="\\{$app}\\Model\\{$table}Model";
    // 驼峰命名转化为下划线
    $table=preg_replace('/((?<=[a-z])(?=[A-Z]))/','_',$table);
    $table=strtolower($table);
    // 通过单例、工厂模式获取对象
    $instance=\phpless\core\Factory::getInstance($model,$pdo);
    // 初始化此 Model 的数据表查询属性
    $instance->table=$db_prefix.$table;
    // 实例化的时候获取数据表的字段
    $instance -> field();
    return $instance;
}

/**
 * 实例化模型类，不需要数据库操作时
 * @param string $table     模型层操作类
 * @param string $construct 构造方法传入参数
 * @return  mixed 是一个通过单例、工厂产生的对象
 */
function model($table,$construct=null)
{
    $app=basename(APP_PATH);
    $model="\\{$app}\\Model\\{$table}Model";
    // 通过单例、工厂模式获取对象
    $instance=\phpless\core\Factory::getInstance($model,$construct);
    return $instance;
}

/**
 * 获取框架的配置信息
 * @param  string $key   配置名称，若不存在则获取所有配置信息
 * @param  string $value 有即为设置配置，无即为获取配置
 * @return string        配置的内容
 */
function config($key=null,$value=null)
{
    // 实例化配置类
    $class_name="\\phpless\\core\\Config";
    $config_class=\phpless\core\Factory::getInstance($class_name);
    // 获取配置
    // 设置配置
    // 获取所有
    if(empty($key)){ # 获取所有
        $result=$config_class;
    }elseif(!empty($key) && !isset($value)){ # 获取配置
        $result = $config_class[$key];
    }elseif(!empty($key) && isset($value)){ # 设置配置
        $result = $config_class[$key] = $value;
    }
    return $result;
}

/**
 * 视图加载函数
 * 'Index/index'，即为视图目录中Index目录下的index.php页面
 * @param string $tpl    模板位置
 * @param mixed $tpl_var 模板变量
 */
function View($tpl,$data='')
{
    $page=APP_VIEW_PATH.$tpl.'.php';
    if(file_exists($page))
        include $page;
    else
        return false;
    return true;
}

/**
 * 获取控制器对象
 * @param string $ctrlClass 控制器名称
 * @return Object 控制器对象
 */
function C($ctrlClass)
{
    // 获取命名空间
    $model=basename(APP_PATH);
    // 拼接类[控制器]
    $controller="{$model}\\Controller\\{$ctrlClass}Controller";
    // 实例化类[控制器]
    $ctrl=\phpless\core\Factory::getInstance($controller);
    return $ctrl;
}

/**
 * 获取客户端$_GET相应的值，如果没有参数则获取所有
 * @param  string $get     name值，$_GET['name']
 * @param  mixed  $default 默认值
 * @param  bool   $is_htmlentities 是否使用 htmlentities() 函数过滤 $post 真 过滤 假 不过滤 默认为真
 * @return mixed           返回客户端的参数
 */
function get($get=null,$default=null,$is_htmlentities=true)
{
    if($get==null)
    {
        $result=$_GET;
    }else if(empty($_GET[$get]))
    {
        $result=null;
    }else{
        $result=$_GET[$get];
    }
    if($default!=null){
        $result=$default;
    }
    if($is_htmlentities)
        $result=phpless_htmlentities($result);
    return $result;
}

/**
 * 获取$_POST相应的值，如果没有参数则获取所有
 * @param  string|array $post     name值，$_POST['name']
 * @param  mixed  $default 默认值
 * @param  bool   $is_htmlentities 是否使用 htmlentities() 函数过滤 $post 真 过滤 假 不过滤 默认为真
 * @return mixed           获取表单提交的值
 */
function post($post=null,$default=null,$is_htmlentities=true)
{
    if($post==null)
    {
        $result=$_POST;
    }else if(empty($_POST[$post]))
    {
        $result=null;
    }else{
        $result=$_POST[$post];
    }
    if($default!=null){
        $result=$default;
    }
    if($is_htmlentities)
        $result=phpless_htmlentities($result);
    return $result;
}

/**
 * 使用 htmlentities() 转译 HTML
 * @param  mixed     $data     转译的字符串|数组
 * @return mixed             结果
 */
function phpless_htmlentities($data)
{
    if(is_array($data)){
        foreach($data as $key => &$value) {
            $value=htmlentities($value,ENT_QUOTES,'UTF-8');
        }
        unset($value);
    }else{
        $data=htmlentities($data,ENT_QUOTES,'UTF-8');
    }
    return $data;
}

/**
 * URL重定向
 * @param string $url 重定向的URL地址
 * @return void
 */
function redirect($url)
{
    if (!headers_sent())
        header('Location: ' . $url);
    else
        echo "<script>window.location.href='{$url}'</script>";
    exit();
}
/**
 * 引人Vendor 中的类库
 * @param string $load 类库的入口文件，实例：Alidayu.TopSdk 即为类库目录.类库的入口文件
 * @return  string 类库的入口文件
 */
function Vendor($load)
{
    // 分解
    $load=explode('.', $load);
    // 若长度不为2则引入错误
    if(count($load)!==2)
    {
        dd('引入 Vendor 错误');
    }
    // 引入框架 Vendor、引入项目 Vendor，如果同时存在则引入框架 Vendor
    // 入口文件
    $vendor_index="\/{$load[0]}\/{$load[1]}.php";
    $phpless_vendor_index_file=PHPLESS_VENDOR.$vendor_index;
    $app_vendor_index_file=APP_VENDOR_PATH.$vendor_index;
    $result="不存在这个入口文件：{$vendor_index}，请检查 Vendor 目录，路径：".PHPLESS_VENDOR;
    if(!is_file($phpless_vendor_index_file)){
        if(!is_file($app_vendor_index_file))
            $result="不存在这个入口文件：{$vendor_index}，请检查 Vendor 目录，路径：".APP_VENDOR_PATH;
        else
            $result=require $app_vendor_index_file;
    }else{
        $result=require $phpless_vendor_index_file;
    }
    return $result;
}

/**
 * 引入第三方类文件
 * 个人理解：
 * ORG 目录中存放一个类文件，以 .class.php 结尾，类名与类文件同名，例如 Page.class.php 文件中就定义了一个 Page 类
 * Vendor <正式>供应商 所以此目录中是一些集成的类库包
 * @param string $class_name 类文件名称 后缀为 .class.php
 * @todo 成功引入以后，实例化须加\ ，例如 $class = new \Page();
 */
function Org($class_name)
{
    // 引入框架 ORG、引入项目 ORG，如果同时存在则引入框架 ORG
    $phpless_org_class_file=PHPLESS_ORG."/{$class_name}.class.php";
    $app_org_class_file=APP_ORG_PATH."/{$class_name}.class.php";
    $result="不存在这个类文件：{$class_name}，请检查 ORG 目录，路径：".PHPLESS_ORG;
    if(!is_file($phpless_org_class_file)){
        if(!is_file($app_org_class_file))
            $result="不存在这个类文件：{$class_name}，请检查 ORG 目录，路径：".APP_ORG_PATH;
        else
            $result=require $app_org_class_file;
    }else{
        $result=require $phpless_org_class_file;
    }
    return $result;
}

/**
 * 引入 Trait
 * @param string $trait_name 类文件名称 后缀为 .class.php
 */
function Traits($trait_name)
{
    // 引入框架 TRAIT、引入项目 TRAIT，如果同时存在则引入框架 TRAIT
    $phpless_trait_file=PHPLESS_TRAIT."/{$trait_name}.trait.php";
    $app_trait_file=APP_TRAIT_PATH."/{$trait_name}.trait.php";
    $result="不存在这个 Trait 文件：{$trait_name}，请检查 TRAIT 目录，路径：".PHPLESS_TRAIT;
    if(!is_file($phpless_trait_file)){
        if(!is_file($app_trait_file))
            $result="不存在这个 Trait 文件：{$trait_name}，请检查 TRAIT 目录，路径：".APP_TRAIT_PATH;
        else
            $result=require $app_trait_file;
    }else{
        $result=require $phpless_trait_file;
    }
    return $result;
}

/**
 * 生成 url 链接地址
 * @param  string $path_info         '控制器/方法'|'模块/控制器/方法'
 * @param  string|array $param         参数、多种形式
 * @return string                     生成的 url
 */
function url($path_info,$param='')
{
    $controller=array();
    // $request_scheme=isset($_SERVER['REQUEST_SCHEME'])?$_SERVER['REQUEST_SCHEME'].'://':'';
    // $server_name=$_SERVER['SERVER_NAME'];
    $script_name=$_SERVER['SCRIPT_NAME'];

    $path_info=trim(trim($path_info,'/'));
    $anchor=strstr($path_info,'#');
    $path_info=str_replace($anchor,'',$path_info);

    $path_arr=explode('/',$path_info);
    $path_info_count=count($path_arr);
    switch($path_info_count){
        case 2:
            $script_name=$script_name;
            $controller['c']=$path_arr[0];
            $controller['a']=$path_arr[1];
            break;
        case 3:
            $file_name=pathinfo($script_name,PATHINFO_FILENAME);
            $script_name=str_replace($file_name, $path_arr[0],$script_name);
            $controller['c']=$path_arr[1];
            $controller['a']=$path_arr[2];
            break;
        default:
            return false;
            break;
    }
    $controller_c_a=array(
        $controller['c']=>$controller['a'],
    );
    $param_type=is_array($param)?'array':'string';
    $url_model=(int)config('URL_MODEL');
    if($param_type==='array' && $url_model===1){
        $param=array_merge($controller_c_a,$param);
        $param_temp=[];
        foreach($param as $key => $value) {
            $param_temp[]=$key.'/'.$value;
        }
        $param='/'.implode('/',$param_temp);
    }elseif($param_type==='array' && $url_model===0){
        $param=array_merge($controller,$param);
        $param='?'.http_build_query($param);
    }elseif($param_type==='string' && $url_model===1){
        $param=str_replace('=','/',$param);
        $param='/'."{$controller['c']}/{$controller['a']}/".str_replace('&','/',$param);
    }elseif($param_type==='string' && $url_model===0){
        $param=str_replace('=','/',$param);
        $param="c/{$controller['c']}/a/{$controller['a']}/".str_replace('&','/',$param);

        $param=trim($param,'/');
        $param=explode('/',$param);
        // 转化为URL参数
        $param_temp=[];
        $count=count($param);
        for($i=0;$i<$count;$i=$i+2){
            $param_temp[$param[$i]]=$param[$i+1];
        }
        $param='?'.http_build_query($param_temp);
    }
    $param=rtrim($param,'/');
    // $url="{$request_scheme}{$server_name}{$script_name}{$param}{$anchor}";
    $url="{$script_name}{$param}{$anchor}";
    return $url;
}

/**
 * 获取完成表名
 * @param string $table_name 数据表的完整名称
 */
function get_table_name($table_name=null)
{
    if(empty($table_name)){
        return false;
    }
    // 获取数据表前缀
    $db_prefix=config('DB_PREFIX');
    if(is_string($table_name)){
        $table_name=$db_prefix.$table_name;
    }elseif(is_array($table_name)){
        $table_name=array_map(function($v) use ($db_prefix){
            return $db_prefix.$v;
        },$array);
    }else{
        $table_name=$db_prefix;
    }
    return $table_name;
}
